package com.tbi.graphcolouring.algorithmconfiguration.evaluator;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.tbi.algorithm.configuration.IEvaluator;
import com.tbi.graphcolouring.BaseGraph;
import com.tbi.graphcolouring.BaseGraph.Node;
import com.tbi.graphcolouring.PopulationEntity;

public class RepairEvaluator implements IEvaluator{
	private BaseGraph graph;
	
	private Map<Integer, Integer> colorMapper = new HashMap<Integer, Integer>();
	private Set<Integer> colorsSet = new HashSet<>();
	
	public RepairEvaluator(BaseGraph graph) {
		this.graph = graph;
	}
	
	public void setGraph(BaseGraph graph) {
		this.graph = graph;
	}

	@Override
	public void evaluate(List<Object> population) {
//		long start = System.currentTimeMillis();
		for(Object obj : population){
			PopulationEntity entity = (PopulationEntity) obj;
			
			graph.setUpColors(entity.colors);
			
			repair(graph);
			int[] cols = graph.getColors();
			normalize(cols);
			
			for(int i : cols){
				colorsSet.add(i);
			}
			
			entity.colors = cols;
			entity.rating = colorsSet.size();
			
			colorsSet.clear();
		}
//		System.out.println("Evaltime: "+(System.currentTimeMillis()-start));
	}
	
	private void repair(BaseGraph graph) {
		for(Node n : graph.getNodes()){
			while(!validateNode(n)){
				n.setColor(n.getColor()-1);
				if(n.getColor() < 0){
					n.setColor(graph.getSize()-1);
				}
			}
		}
	}
	
	private boolean validateNode(Node n){
		for(Node connected : n.getConnections()){
			if(n.getColor() == connected.getColor())
				return false;
		}
		return true;
	}
	
	private void normalize(int[] colors) {
		for (int i = 0; i < colors.length; i++) {
			if(!colorMapper.containsKey(colors[i])){
				colorMapper.put(colors[i], colorMapper.size());
			}
		}
		for (int i = 0; i < colors.length; i++) {
			colors[i] = colorMapper.get(colors[i]);
		}
		colorMapper.clear();
	}
}
